package com.sxt.service.impl;

import com.sxt.entity.Basket;
import com.sxt.entity.Prod;
import com.sxt.entity.Sku;
import com.sxt.mapper.BasketMapper;
import com.sxt.model.MoneyResult;
import com.sxt.model.ShopCartItem;
import com.sxt.service.BasketService;
import com.sxt.service.ProdService;
import com.sxt.service.SkuService;

import cn.hutool.json.JSONUtil;
import lombok.extern.slf4j.Slf4j;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import org.apache.dubbo.config.annotation.Reference;
import org.apache.dubbo.config.annotation.Service;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.StringUtils;

/**
 * <p>
 * 购物车 服务实现类
 * </p>
 *
 * @author liangtiandong
 * @since 2019-12-17
 */
@Service
@Slf4j
public class BasketServiceImpl extends ServiceImpl<BasketMapper, Basket> implements BasketService {

	@Autowired
	private BasketMapper basketMapper ;

	@Reference(check = false)
	private ProdService prodService ;

	@Reference(check = false)
	private SkuService skuService ;

	@Override
	public void addCart(Basket basket) {
		log.info("添加到购物车，数据为{}",JSONUtil.toJsonPrettyStr(basket));
		/**
		 * 1 怎么把数据添加到购物车里面
		 * 添加分为2 种
		 * 1 之前用户没有该商品 user_id sku_id shop_id(隐含的) 因为联合索引user_id + sku_id + shop_id 不能有相同的值
		 * 2 之前用户有该商品
		 */
		Basket cartItemDb = basketMapper.selectOne(new LambdaQueryWrapper<Basket>().
				eq(Basket::getShopId, basket.getShopId())
				.eq(Basket::getUserId,basket.getUserId())
				.eq(Basket::getSkuId,basket.getSkuId())
				);
		if(cartItemDb==null) { // 之前没有该商品 不存在，新增该条目
			basket.setBasketDate(LocalDateTime.now());
			basketMapper.insert(basket); // 把新的值保存起来
		}else { // 存在，修改条目的数量
			Integer basketCount = cartItemDb.getBasketCount();
			Integer totalCount = basketCount + basket.getBasketCount() ;
			cartItemDb.setBasketCount(totalCount) ;
			basketMapper.updateById(cartItemDb) ;
		}

	}

	@Override
	public Integer getTotalCount(String userId) {
		log.info("查询用户{}的购物车总条数",userId);
		//SELECT SUM(basket_count) FROM basket WHERE user_id = 2 ; select ${colums} from  baskert where user_id = #{user_id} ;
		List<Object> totalCount = basketMapper.selectObjs(new QueryWrapper<Basket>().select("SUM(basket_count)").eq("user_id", userId));
		if(totalCount ==null || totalCount.isEmpty() || totalCount.get(0) == null) {
			return 0 ;
		}
		String totalCountStr = totalCount.get(0).toString(); //object = null totalCount.add(null);
		return Integer.valueOf(totalCountStr);
	}

	/**
	 * 得到一个用户的购物车条目数据
	 */
	@Override
	public List<ShopCartItem> getCartInfo(String userId) {
		log.info("查询用户{}的购物车数据",userId);
		List<Basket> baskets = basketMapper.selectList(new LambdaQueryWrapper<Basket>().eq(Basket::getUserId, userId)) ;
		List<ShopCartItem> cartItems = builderCartItem(baskets);
		return cartItems;
	}

	private List<ShopCartItem> builderCartItem(List<Basket> baskets) {
		if(baskets==null || baskets.isEmpty()) {
			return Collections.emptyList() ;
		}
		List<ShopCartItem> cartItems = new ArrayList<ShopCartItem>();
		for (Basket basket : baskets) {
			ShopCartItem  cartItem = basket2ShopCartItem(basket);
			cartItems.add(cartItem) ;
		}
		return cartItems;
	}

	/**
	 * 使用数据库里面的购物车条目得到要显示的数据
	 * @param basket
	 * @return
	 */
	private ShopCartItem basket2ShopCartItem(Basket basket) {
		ShopCartItem shopCartItem = new ShopCartItem();
		shopCartItem.setProdCount(basket.getBasketCount());
		Prod prod = prodService.getProdPicAndProdName(basket.getProdId());
		shopCartItem.setProdName(prod.getProdName());
		Sku sku = skuService.getById(basket.getSkuId());
		shopCartItem.setPic(StringUtils.hasText(sku.getPic())?sku.getPic():prod.getPic()); // 要优先显示sku的图片
		shopCartItem.setSkuName(sku.getSkuName());
		shopCartItem.setPrice(sku.getPrice()==null?prod.getPrice():sku.getPrice());
		shopCartItem.setProdId(basket.getProdId());
		shopCartItem.setSkuId(basket.getSkuId());
		shopCartItem.setBasketId(basket.getBasketId());
		return shopCartItem;
	}

	/**
	 * 怎么计算总金额
	 */
	@Override
	public MoneyResult getTotalMoney(List<Long> basketIds) {
		MoneyResult moneyResult = new MoneyResult();
		if(basketIds==null||basketIds.isEmpty()) {
			moneyResult.setFinalMoney(new BigDecimal(0.00));
			moneyResult.setTotalMoney(new BigDecimal(0.00));
			return moneyResult;
		}
		List<Basket> baskets = basketMapper.selectList(new LambdaQueryWrapper<Basket>().in(Basket::getBasketId, basketIds));
		BigDecimal totalMoney = new BigDecimal("0.00") ;
		int totalCount = 0  ;
		for (Basket basket : baskets) {
			Long skuId = basket.getSkuId();
			Sku sku = skuService.getById(skuId);
			Integer basketCount = basket.getBasketCount();
			totalCount += basketCount ;
			BigDecimal decimal = sku.getPrice().multiply(new BigDecimal(basketCount)); // 单品的价格
			totalMoney = totalMoney.add(decimal) ; // 计算总价格

		}
		moneyResult.setTotalMoney(totalMoney.setScale(2, BigDecimal.ROUND_HALF_UP));
		moneyResult.setSubtractMone(new BigDecimal("0.00")); // 满减金额和优惠相关
		moneyResult.setFinalMoney(moneyResult.getTotalMoney().add(moneyResult.getSubtractMone().negate()));
		moneyResult.setTotal(totalCount);
		return moneyResult;
	}

	@Override
	public List<ShopCartItem> getOrderConfirm(List<Long> basketIds) {
		log.info("通过id{}查询购物车的条目",basketIds);
		if(basketIds==null || basketIds.isEmpty()) {
			return Collections.emptyList() ;
		}
		List<Basket> baskets = basketMapper.selectList(new LambdaQueryWrapper<Basket>().in(Basket::getBasketId, basketIds));
		List<ShopCartItem> cartItems = builderCartItem(baskets);
		return cartItems;
	}

	@Override
	public void clearCart(List<ShopCartItem> cartItems) {
		if(cartItems==null || cartItems.isEmpty()) {
			return ;
		}
		List<Long> cartIds = new ArrayList<Long>(cartItems.size());
		for (ShopCartItem shopCartItem : cartItems) {
			cartIds.add(shopCartItem.getBasketId()) ;
		}
		basketMapper.delete(new LambdaQueryWrapper<Basket>().in(Basket::getBasketId, cartIds)) ;
	}
}
